package de.pyranja.jdbm;

import static org.junit.Assert.*;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Map;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

import org.apache.jdbm.DB;
import org.apache.jdbm.DBMaker;
import org.junit.After;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;

@Ignore
public class FirstStep {
	
	public static final String DB_FILE = "D:/Playground/jdbm_test/test";
	public static final String MAP_NAME = "map";
	
	public static final int THREADS = 20;
	protected static final int INSERTS = 10;
	DB db;
	
	@Before
	public void setUp() {
		db = DBMaker.openFile(DB_FILE).make();
	}
	
	@After
	public void tearDown() {
		db.close();
	}
	
	@Test
	public void create_jdbm() {
		Map<Integer,String> map = db.createTreeMap(MAP_NAME);
		System.out.println(map);
		map.put(1, "ONE");
		map.put(2, "TWO");
		System.out.println(map);
		db.commit();
	}
	
	@Test
	public void open_existing() {
		Map<Integer,String> map = db.getTreeMap(MAP_NAME);
		System.out.println(map);
		map.put(3, "THREE");
		System.out.println(map);
	}
	
	@Test
	public void clear() {
		db.deleteCollection(MAP_NAME);
	}
	
	private static class Inserter implements Runnable {
		Map<String,String> map;
		int id;
		CountDownLatch join;
		DB db;
		@Override
		public void run() {
			for (int i = 0; i < INSERTS; i++) {
				map.put("THREAD:"+id+":INSERT:"+i, "DONE");
			}
			db.commit();
			join.countDown();
		}
	}
	
	@Test
	public void threaded_writes() throws InterruptedException {
		db.deleteCollection("THREAD_MAP");
		Executor exec = Executors.newCachedThreadPool();
		Map<String,String> map = db.createTreeMap("THREAD_MAP");
		Collection<Runnable> runners = new ArrayList<Runnable>();
		CountDownLatch join = new CountDownLatch(THREADS);
		for (int i = 0; i < THREADS; i++) {
			final Inserter curr = new Inserter();
			curr.map = map;
			curr.id = i;
			curr.join = join;
			curr.db = db;
			runners.add(curr);
		}
		for (Runnable command : runners) {
			exec.execute(command);
		}
		join.await(30, TimeUnit.SECONDS);
		assertEquals(THREADS * INSERTS, map.size());
		System.out.println(map);
	}
}
